package repository

import (
	"errors"
	"gitee.com/fierce_wolf/go-fox-edge-common/commEntity"
	"gitee.com/fierce_wolf/go-fox-edge-common/commEntityManager"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Differ"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Json"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Map"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Method"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/String"
	"gitee.com/fierce_wolf/go-fox-edge-common/edgeEntity"
	"strings"
)

type repoLocalCompService struct {
}

func (e *repoLocalCompService) GetCompEntityList(body map[string]interface{}) ([]commEntity.IEntity, error) {
	// 提取业务参数
	compRepo := Map.GetString(body, "compRepo", "")
	compType := Map.GetString(body, "compType", "")
	keyWord := Map.GetString(body, "keyWord", "")

	// 简单校验参数
	if Method.HasEmpty(compRepo, compType) {
		return nil, errors.New("参数不能为空: compRepo, compType")
	}

	list := commEntityManager.FindEntityList(edgeEntity.Type.RepoCompEntity.Type(), func(value commEntity.IEntity) bool {
		compEntity := value.(*edgeEntity.RepoCompEntity)

		if compRepo != compEntity.CompRepo {
			return false
		}
		if compType != compEntity.CompType {
			return false
		}

		if compType == "jar-decoder" || compType == "jsp-decoder" || compType == "device-template" {
			if Method.HasEmpty(keyWord) {
				return true
			}

			manufacturer := Map.GetString(compEntity.CompParam, "manufacturer", "")
			deviceType := Map.GetString(compEntity.CompParam, "deviceType", "")

			if strings.Contains(strings.ToLower(manufacturer), strings.ToLower(keyWord)) {
				return true
			}
			if strings.Contains(strings.ToLower(deviceType), strings.ToLower(keyWord)) {
				return true
			}
			if strings.Contains(strings.ToLower(compEntity.CompName), strings.ToLower(keyWord)) {
				return true
			}

			return false
		}

		if compType == "iot-template" {
			if Method.HasEmpty(keyWord) {
				return true
			}

			iotName := Map.GetString(compEntity.CompParam, "iotName", "")

			if strings.Contains(strings.ToLower(iotName), strings.ToLower(keyWord)) {
				return true
			}
			if strings.Contains(strings.ToLower(compEntity.CompName), strings.ToLower(keyWord)) {
				return true
			}

			return false
		}

		if compType == "app-service" {
			if Method.HasEmpty(keyWord) {
				return true
			}

			appName := Map.GetString(compEntity.CompParam, "appName", "")
			appType := Map.GetString(compEntity.CompParam, "appType", "")

			if strings.Contains(strings.ToLower(appName), strings.ToLower(keyWord)) {
				return true
			}
			if strings.Contains(strings.ToLower(appType), strings.ToLower(keyWord)) {
				return true
			}

			return false
		}

		return true
	})

	return list, nil
}

func (e *repoLocalCompService) DeleteCompEntity(compId int64) error {
	// 简单验证
	if compId == 0 {
		return errors.New("参数不能为空: compId")
	}

	// 获得实体
	entity := commEntityManager.GetEntityById(edgeEntity.Type.RepoCompEntity.Type(), compId)
	if entity == nil {
		return errors.New("找不到对应的组件:" + String.ToString(compId))
	}
	compEntity := entity.(*edgeEntity.RepoCompEntity)

	// 检查：实体中的依赖关系，避免数据之间依赖关系失效
	if compEntity.CompType == "jsp-decoder" {
		operateList, err := LocalOperate.GetOperateEntityList(compEntity)
		if err != nil {
			return err
		}

		if len(operateList) != 0 {
			return errors.New("该组件下面，已经定义了操作方法，请先删除这些操作方法后，再删除组件!")
		}
	}

	// 检查：实体中的依赖关系，避免数据之间依赖关系失效
	if compEntity.CompType == "jsn-decoder" {
		operateList := LocalJsnModel.GetDeviceModelEntityList(compEntity)

		if len(operateList) != 0 {
			return errors.New("该组件下面，已经定义了操作方法，请先删除这些操作方法后，再删除组件!")
		}
	}

	// 检查：实体中的依赖关系，避免数据之间依赖关系失效
	if compEntity.CompType == "device-template" {
		manufacturer := Map.GetString(compEntity.CompParam, "manufacturer", "")
		deviceType := Map.GetString(compEntity.CompParam, "deviceType", "")
		subsetName := Map.GetString(compEntity.CompParam, "subsetName", "")

		operateList := LocalDevTemplate.GetDevTemplateEntityList(manufacturer, deviceType, subsetName)

		if len(operateList) != 0 {
			return errors.New("该组件下面，已经定义了操作方法，请先删除这些操作方法后，再删除组件!")
		}
	}

	// 检查：实体中的依赖关系，避免数据之间依赖关系失效
	if compEntity.CompType == "iot-template" {
		iotName := Map.GetString(compEntity.CompParam, "iotName", "")
		subsetName := Map.GetString(compEntity.CompParam, "subsetName", "")

		operateList := LocalIotTemplate.GetIotTemplateEntityList(iotName, subsetName)

		if len(operateList) != 0 {
			return errors.New("该组件下面，已经定义了操作方法，请先删除这些操作方法后，再删除组件!")
		}
	}

	commEntityManager.DeleteEntity(entity)

	return nil
}

func (e *repoLocalCompService) GetRepoCompEntity(id int64) *edgeEntity.RepoCompEntity {
	exist := commEntityManager.GetEntityById(edgeEntity.Type.RepoCompEntity.Type(), id)
	if exist == nil {
		return nil
	}

	return exist.(*edgeEntity.RepoCompEntity)
}

func (e *repoLocalCompService) InstallVersion(compType string, data map[string]interface{}) (map[string]interface{}, error) {
	if compType == "jsp-decoder" {
		return e.installJspDecoderEntity(data)
	}
	if compType == "jsn-decoder" {
		return e.installJsnDecoderEntity(data)
	}
	if compType == "device-template" {
		return e.installDevTemplateEntity(data)
	}
	if compType == "iot-template" {
		return e.installIotTemplateEntity(data)
	}

	return nil, errors.New("该组件类型，不支持本地上传")
}

func (e *repoLocalCompService) installJspDecoderEntity(data map[string]interface{}) (map[string]interface{}, error) {
	// 提取业务参数
	deviceType := Map.GetString(data, "deviceType", "")
	manufacturer := Map.GetString(data, "manufacturer", "")
	scriptId := Map.GetString(data, "scriptId", "")
	groupName := Map.GetString(data, "groupName", "")
	operates := Map.GetSlice(data, "operates", nil)

	if Method.HasEmpty(deviceType, manufacturer, scriptId, groupName, operates) {
		return nil, errors.New("缺少参数： deviceType, manufacturer, scriptId, groupName, operates")
	}

	repoCompEntity := edgeEntity.Type.RepoCompEntity.Instance()
	repoCompEntity.CompRepo = "local"
	repoCompEntity.CompType = "jsp-decoder"
	repoCompEntity.CompName = manufacturer + ":" + deviceType

	// 如果组件对象不存在，那么就创建一个新的组件对象
	existCompEntity, err := commEntityManager.GetEntityByServiceKey(repoCompEntity.Type(), repoCompEntity.MakeServiceKey())
	if err != nil {
		return nil, err
	}
	if existCompEntity == nil {
		repoCompEntity.CompParam["scriptId"] = scriptId
		repoCompEntity.CompParam["groupName"] = groupName
		repoCompEntity.CompParam["manufacturer"] = manufacturer
		repoCompEntity.CompParam["deviceType"] = deviceType

		commEntityManager.InsertEntity(repoCompEntity)
	} else {
		repoCompEntity = existCompEntity.(*edgeEntity.RepoCompEntity)
	}

	// 组织成天MAP关系
	dstOperateMap := make(map[string]*edgeEntity.OperateEntity)
	for _, operate := range operates {
		operateEntity := edgeEntity.Type.OperateEntity.Instance()
		err := Json.BuildObjectByMap(operate, operateEntity)
		if err != nil {
			return nil, err
		}

		operateEntity.Manufacturer = manufacturer
		operateEntity.DeviceType = deviceType

		dstOperateMap[operateEntity.OperateName] = operateEntity
	}

	// 获得已经存在的操作列表
	operateList := commEntityManager.FindEntityList(edgeEntity.Type.OperateEntity.Type(), func(value commEntity.IEntity) bool {
		entity := value.(*edgeEntity.OperateEntity)

		if entity.EngineType != "JavaScript" {
			return false
		}
		if entity.Manufacturer != manufacturer {
			return false
		}
		if entity.DeviceType != deviceType {
			return false
		}

		return true
	})

	srcOperateMap := make(map[string]*edgeEntity.OperateEntity)
	for _, v := range operateList {
		entity := v.(*edgeEntity.OperateEntity)
		srcOperateMap[entity.OperateName] = entity
	}

	addList := make(map[string]interface{})
	delList := make(map[string]interface{})
	eqlList := make(map[string]interface{})
	Differ.Set.DifferByKey(srcOperateMap, dstOperateMap, &addList, &delList, &eqlList)

	for key := range addList {
		operateEntity := dstOperateMap[key]
		operateEntity.BaseEntity.Id = 0
		commEntityManager.InsertEntity(operateEntity)
	}
	for key := range delList {
		operateEntity := srcOperateMap[key]
		commEntityManager.DeleteEntity(operateEntity)
	}
	for key := range eqlList {
		dstEntity := dstOperateMap[key]
		srcEntity := srcOperateMap[key]
		if dstEntity.MakeServiceKey() != srcEntity.MakeServiceKey() {
			continue
		}

		dstEntity.BaseEntity.Id = srcEntity.BaseEntity.Id
		commEntityManager.UpdateEntity(dstEntity)
	}

	// 获得版本日期
	updateTime := Map.GetInt64(data, "updateTime", 0)

	// 更新：安装版本的信息
	install := make(map[string]interface{})
	install["updateTime"] = updateTime
	install["description"] = data["description"]
	install["id"] = data["id"]

	// 更新版本信息
	repoCompEntity.CompParam["installVersion"] = install
	commEntityManager.UpdateEntity(repoCompEntity)

	return nil, nil
}

func (e *repoLocalCompService) installJsnDecoderEntity(data map[string]interface{}) (map[string]interface{}, error) {
	// 提取业务参数
	deviceType := Map.GetString(data, "deviceType", "")
	manufacturer := Map.GetString(data, "manufacturer", "")
	modelId := Map.GetString(data, "modelId", "")
	groupName := Map.GetString(data, "groupName", "")
	objects := Map.GetSlice(data, "objects", nil)

	if Method.HasEmpty(deviceType, manufacturer, modelId, groupName, objects) {
		return nil, errors.New("缺少参数： deviceType, manufacturer, modelId, groupName, objects")
	}

	repoCompEntity := edgeEntity.Type.RepoCompEntity.Instance()
	repoCompEntity.CompRepo = "local"
	repoCompEntity.CompType = "jsn-decoder"
	repoCompEntity.CompName = manufacturer + ":" + deviceType

	// 如果组件对象不存在，那么就创建一个新的组件对象
	existCompEntity, err := commEntityManager.GetEntityByServiceKey(repoCompEntity.Type(), repoCompEntity.MakeServiceKey())
	if err != nil {
		return nil, err
	}
	if existCompEntity == nil {
		repoCompEntity.CompParam["compId"] = modelId
		repoCompEntity.CompParam["groupName"] = groupName
		repoCompEntity.CompParam["manufacturer"] = manufacturer
		repoCompEntity.CompParam["deviceType"] = deviceType

		commEntityManager.InsertEntity(repoCompEntity)
	} else {
		repoCompEntity = existCompEntity.(*edgeEntity.RepoCompEntity)
	}

	// 组织成天MAP关系
	dstOperateMap := make(map[string]*edgeEntity.DeviceModelEntity)
	for _, object := range objects {
		modelEntity := edgeEntity.Type.DeviceModelEntity.Instance()
		err := Json.BuildObjectByMap(object, modelEntity)
		if err != nil {
			return nil, err
		}

		modelEntity.Manufacturer = manufacturer
		modelEntity.DeviceType = deviceType

		dstOperateMap[modelEntity.ModelName] = modelEntity
	}

	// 获得已经存在的操作列表
	objectList := commEntityManager.FindEntityList(edgeEntity.Type.DeviceModelEntity.Type(), func(value commEntity.IEntity) bool {
		entity := value.(*edgeEntity.DeviceModelEntity)

		if entity.DeviceType != deviceType {
			return false
		}
		if entity.Manufacturer != manufacturer {
			return false
		}

		return true
	})

	srcOperateMap := make(map[string]*edgeEntity.DeviceModelEntity)
	for _, v := range objectList {
		entity := v.(*edgeEntity.DeviceModelEntity)
		srcOperateMap[entity.ModelName] = entity
	}

	addList := make(map[string]interface{})
	delList := make(map[string]interface{})
	eqlList := make(map[string]interface{})
	Differ.Set.DifferByKey(srcOperateMap, dstOperateMap, &addList, &delList, &eqlList)

	for key := range addList {
		modelEntity := dstOperateMap[key]
		modelEntity.BaseEntity.Id = 0
		commEntityManager.InsertEntity(modelEntity)
	}
	for key := range delList {
		modelEntity := srcOperateMap[key]
		commEntityManager.DeleteEntity(modelEntity)
	}
	for key := range eqlList {
		dstEntity := dstOperateMap[key]
		srcEntity := srcOperateMap[key]
		if dstEntity.MakeServiceKey() != srcEntity.MakeServiceKey() {
			continue
		}

		dstEntity.BaseEntity.Id = srcEntity.BaseEntity.Id
		commEntityManager.UpdateEntity(dstEntity)
	}

	// 获得版本日期
	updateTime := Map.GetInt64(data, "updateTime", 0)

	// 更新：安装版本的信息
	install := make(map[string]interface{})
	install["updateTime"] = updateTime
	install["description"] = data["description"]
	install["id"] = data["id"]

	// 更新版本信息
	repoCompEntity.CompParam["installVersion"] = install
	commEntityManager.UpdateEntity(repoCompEntity)

	return nil, nil
}

func (e *repoLocalCompService) installDevTemplateEntity(data map[string]interface{}) (map[string]interface{}, error) {
	// 提取业务参数
	deviceType := Map.GetString(data, "deviceType", "")
	manufacturer := Map.GetString(data, "manufacturer", "")
	subsetName := Map.GetString(data, "subsetName", "")
	templateId := Map.GetString(data, "templateId", "")
	groupName := Map.GetString(data, "groupName", "")
	objects := Map.GetSlice(data, "objects", nil)

	if Method.HasEmpty(deviceType, manufacturer, subsetName, templateId, groupName, objects) {
		return nil, errors.New("缺少参数：deviceType, manufacturer, subsetName, templateId, groupName, objects")
	}

	repoCompEntity := edgeEntity.Type.RepoCompEntity.Instance()
	repoCompEntity.CompRepo = "local"
	repoCompEntity.CompType = "device-template"
	repoCompEntity.CompName = manufacturer + ":" + deviceType + ":" + subsetName

	// 如果组件对象不存在，那么就创建一个新的组件对象
	existCompEntity, err := commEntityManager.GetEntityByServiceKey(repoCompEntity.Type(), repoCompEntity.MakeServiceKey())
	if err != nil {
		return nil, err
	}
	if existCompEntity == nil {
		repoCompEntity.CompParam["compId"] = templateId
		repoCompEntity.CompParam["groupName"] = groupName
		repoCompEntity.CompParam["manufacturer"] = manufacturer
		repoCompEntity.CompParam["deviceType"] = deviceType
		repoCompEntity.CompParam["subsetName"] = subsetName

		commEntityManager.InsertEntity(repoCompEntity)
	} else {
		repoCompEntity = existCompEntity.(*edgeEntity.RepoCompEntity)
	}

	// 组织成天MAP关系
	dstOperateMap := make(map[string]*edgeEntity.DeviceTemplateEntity)
	for _, object := range objects {
		modelEntity := edgeEntity.Type.DeviceTemplateEntity.Instance()
		err := Json.BuildObjectByMap(object, modelEntity)
		if err != nil {
			return nil, err
		}

		modelEntity.Manufacturer = manufacturer
		modelEntity.DeviceType = deviceType
		modelEntity.SubsetName = subsetName

		dstOperateMap[modelEntity.MakeServiceKey()] = modelEntity
	}

	// 获得已经存在的操作列表
	objectList := commEntityManager.FindEntityList(edgeEntity.Type.DeviceTemplateEntity.Type(), func(value commEntity.IEntity) bool {
		entity := value.(*edgeEntity.DeviceTemplateEntity)

		if entity.DeviceType != deviceType {
			return false
		}
		if entity.Manufacturer != manufacturer {
			return false
		}
		if entity.SubsetName != subsetName {
			return false
		}

		return true
	})

	srcOperateMap := make(map[string]*edgeEntity.DeviceTemplateEntity)
	for _, v := range objectList {
		entity := v.(*edgeEntity.DeviceTemplateEntity)
		srcOperateMap[entity.MakeServiceKey()] = entity
	}

	addList := make(map[string]interface{})
	delList := make(map[string]interface{})
	eqlList := make(map[string]interface{})
	Differ.Set.DifferByKey(srcOperateMap, dstOperateMap, &addList, &delList, &eqlList)

	for key := range addList {
		modelEntity := dstOperateMap[key]
		modelEntity.BaseEntity.Id = 0
		commEntityManager.InsertEntity(modelEntity)
	}
	for key := range delList {
		modelEntity := srcOperateMap[key]
		commEntityManager.DeleteEntity(modelEntity)
	}
	for key := range eqlList {
		dstEntity := dstOperateMap[key]
		srcEntity := srcOperateMap[key]
		if dstEntity.MakeServiceKey() != srcEntity.MakeServiceKey() {
			continue
		}

		dstEntity.BaseEntity.Id = srcEntity.BaseEntity.Id
		commEntityManager.UpdateEntity(dstEntity)
	}

	// 获得版本日期
	updateTime := Map.GetInt64(data, "updateTime", 0)

	// 更新：安装版本的信息
	install := make(map[string]interface{})
	install["updateTime"] = updateTime
	install["description"] = data["description"]
	install["id"] = data["id"]

	// 更新版本信息
	repoCompEntity.CompParam["installVersion"] = install
	commEntityManager.UpdateEntity(repoCompEntity)

	return nil, nil
}

func (e *repoLocalCompService) installIotTemplateEntity(data map[string]interface{}) (map[string]interface{}, error) {
	// 提取业务参数
	iotName := Map.GetString(data, "iotName", "")
	subsetName := Map.GetString(data, "subsetName", "")
	templateId := Map.GetString(data, "templateId", "")
	groupName := Map.GetString(data, "groupName", "")
	objects := Map.GetSlice(data, "objects", nil)

	if Method.HasEmpty(iotName, subsetName, templateId, groupName, objects) {
		return nil, errors.New("缺少参数：deviceType, manufacturer, subsetName, templateId, groupName, objects")
	}

	repoCompEntity := edgeEntity.Type.RepoCompEntity.Instance()
	repoCompEntity.CompRepo = "local"
	repoCompEntity.CompType = "iot-template"
	repoCompEntity.CompName = iotName + ":" + subsetName

	// 如果组件对象不存在，那么就创建一个新的组件对象
	existCompEntity, err := commEntityManager.GetEntityByServiceKey(repoCompEntity.Type(), repoCompEntity.MakeServiceKey())
	if err != nil {
		return nil, err
	}
	if existCompEntity == nil {
		repoCompEntity.CompParam["compId"] = templateId
		repoCompEntity.CompParam["groupName"] = groupName
		repoCompEntity.CompParam["iotName"] = iotName
		repoCompEntity.CompParam["subsetName"] = subsetName

		commEntityManager.InsertEntity(repoCompEntity)
	} else {
		repoCompEntity = existCompEntity.(*edgeEntity.RepoCompEntity)
	}

	// 组织成天MAP关系
	dstOperateMap := make(map[string]*edgeEntity.IotTemplateEntity)
	for _, object := range objects {
		modelEntity := edgeEntity.Type.IotTemplateEntity.Instance()
		err := Json.BuildObjectByMap(object, modelEntity)
		if err != nil {
			return nil, err
		}

		modelEntity.IotName = iotName
		modelEntity.SubsetName = subsetName

		dstOperateMap[modelEntity.MakeServiceKey()] = modelEntity
	}

	// 获得已经存在的操作列表
	objectList := commEntityManager.FindEntityList(edgeEntity.Type.IotTemplateEntity.Type(), func(value commEntity.IEntity) bool {
		entity := value.(*edgeEntity.IotTemplateEntity)

		if entity.IotName != iotName {
			return false
		}
		if entity.SubsetName != subsetName {
			return false
		}

		return true
	})

	srcOperateMap := make(map[string]*edgeEntity.IotTemplateEntity)
	for _, v := range objectList {
		entity := v.(*edgeEntity.IotTemplateEntity)
		srcOperateMap[entity.MakeServiceKey()] = entity
	}

	addList := make(map[string]interface{})
	delList := make(map[string]interface{})
	eqlList := make(map[string]interface{})
	Differ.Set.DifferByKey(srcOperateMap, dstOperateMap, &addList, &delList, &eqlList)

	for key := range addList {
		modelEntity := dstOperateMap[key]
		modelEntity.BaseEntity.Id = 0
		commEntityManager.InsertEntity(modelEntity)
	}
	for key := range delList {
		modelEntity := srcOperateMap[key]
		commEntityManager.DeleteEntity(modelEntity)
	}
	for key := range eqlList {
		dstEntity := dstOperateMap[key]
		srcEntity := srcOperateMap[key]
		if dstEntity.MakeServiceKey() != srcEntity.MakeServiceKey() {
			continue
		}

		dstEntity.BaseEntity.Id = srcEntity.BaseEntity.Id
		commEntityManager.UpdateEntity(dstEntity)
	}

	// 获得版本日期
	updateTime := Map.GetInt64(data, "updateTime", 0)

	// 更新：安装版本的信息
	install := make(map[string]interface{})
	install["updateTime"] = updateTime
	install["description"] = data["description"]
	install["id"] = data["id"]

	// 更新版本信息
	repoCompEntity.CompParam["installVersion"] = install
	commEntityManager.UpdateEntity(repoCompEntity)

	return nil, nil
}
